﻿using Novel.Web.Models.Entity;
using Novel.Web.Models.Novel;
using Novel.Web.Models.Novel.output;
using Novel.Web.Models.Repository;
using SqlSugar;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml;
using XjjXmm.FrameWork.ToolKit;
using XjjXmm.Infrastructure.Repository;
using XjjXmm.Infrastructure.Repository.Model;
using XjjXmm.Spider;
using XjjXmm.Spider.Entity;

namespace Novel.Web.Models
{
    public class NovelService
    {
        // private readonly ISqlSugarClient sqlSugarClient;
        private readonly IConfiguration configuration;
        private readonly MenuService menuService;

        private readonly IBookRepository bookRepository;
        private readonly IBookExtensionRepository bookExtensionRepository;
        private readonly IChapterRepository chapterRepository;

        public NovelService(MenuService menuService,
            IBookRepository bookRepository,
            IBookExtensionRepository bookExtensionRepository,
            IChapterRepository chapterRepository,
            ISqlSugarClient sqlSugarClient,
            IConfiguration configuration)
        {
            // this.sqlSugarClient = sqlSugarClient;
            this.configuration = configuration;
            this.menuService = menuService;
            this.bookRepository = bookRepository;
            this.bookExtensionRepository = bookExtensionRepository;
            this.chapterRepository = chapterRepository;

        }


        //public async Task<dynamic> GetIndexNovel()
        //{
        //    var dict = new Dictionary<string, List<BookEntity>>();


        //    foreach(var menu in menuService.GetMenus())
        //    {
        //        dict.Add(menu.Action, await GetNovelByCategory(menu.Action, 1, 20));
        //    }

        //    return dict;                                                                 
        //}

        public async Task<List<BookEntity>> GetTop(MenuEnum? menu, int size)
        {

            var result = await bookRepository.Queryable()
           .Where(menu != null, t => t.Category == menu.ToDescription())
           .LeftJoin<BookExtenstionEntity>((t, b) => t.Id == b.Id)
           .OrderByDesc((t, b) => b.Viewer)
           .ToPage(1, size);

            return result.Data;
        }

        public async Task<List<BookEntity>> GetHot(MenuEnum? menu, int size)
        {
            var result = await bookRepository.Queryable()
           .Where(menu != null, t => t.Category == menu.ToDescription())
           .LeftJoin<BookExtenstionEntity>((t, b) => t.Id == b.Id)
           .OrderByDesc((t, b) => b.Gooder)
           .ToPage(1, size);

            return result.Data;
        }


        public async Task<PageOutput<BookEntity>> GetNovelByCategory(PageInput<string> pageInput)
        {

            var result = await bookRepository.Queryable()
                .Where(!string.IsNullOrEmpty(pageInput.Filter), t => t.Category == pageInput.Filter)
                //.InnerJoin<NovelPoolEntity>((t, n) => t.Title == n.Title && t.Author == n.Author)
                .OrderByDesc(t => t.UpdateTime)
                .ToPage(pageInput.CurrentPage, pageInput.PageSize);

            return result;
        }

        public async Task<BookEntity> GetNovel(long id)
        {
            return await bookRepository.Queryable()
                            .Where(t => t.Id == id)
                           .ToFirst();
        }

        public async Task<List<BookChapterEntity>> GetChaptersByNovelId(long id)
        {
            var tableName = chapterRepository.GetTableName(id);

            // var res = await sqlSugarClient.Queryable< BookChapter >  ().SplitTable(t => t.InTableNames(tableName)).Where(t => t.NovelId == id) .ToListAsync();
            return await chapterRepository.Queryable().SplitTable(t => t.InTableNames(tableName)).Where(t => t.NovelId == id)
                //.InnerJoin<BookEntity>((a, t) => t.Id == id)
                //.InnerJoin<NovelPoolEntity>((a, t, n) => t.Title == n.Title && t.Author == n.Author && a.NovelId == n.Id)
                .ToList();
        }

        /* public async Task<BookEntity> GetNovelByChapterlId(long id)
         {
             var tableName = chapterRepository.GetTableName(id);
             var chapterQuery = 
             bookRepository.Queryable()
                 .Join<BookChapter>((t,b)=>t.Id == b.NovelId)
                 .SplitTable()
             *//* return await sqlSugarClient.Queryable<BookEntity>()
                             //.InnerJoin<NovelPoolEntity>((t, n) => t.Title == n.Title && t.Author == n.Author)
                             .InnerJoin<BookChapter>((t, n) => n.NovelId == t.Id)
                             .Where((t, n) => n.Id == id)
                             .FirstAsync();*//*
             return null;
         }*/


        public async Task<IEnumerable<string>> GetChapterContent(long nid, long cid)
        {
            var folder = configuration["BookFolder"];

            var file = Path.Combine(folder, ChapterSplitService.GetFirstCode(nid.ToString()), nid.ToString());
            if (!File.Exists(file + ".xml.7z"))
            {
                throw new Exception("文件不存在");
            }

            if (!File.Exists(file + ".xml"))
            {
                await CompressKit.UnCompress7z(file + ".xml.7z");
            }

            string content = "";
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            settings.IgnoreWhitespace = true;
            settings.Async = true;

            var hasFind = false;
            using (XmlReader rd = XmlReader.Create(file + ".xml", settings))
            {
                rd.MoveToContent();
                while (rd.Read())
                {
                    if (rd.NodeType == XmlNodeType.Element && rd.Name == "chapter" && rd["id"] == cid.ToString())
                    {
                        hasFind = true;
                        //Console.WriteLine(rd.ReadElementContentAsString());


                    }
                    else if (hasFind && rd.NodeType == XmlNodeType.Element && rd.Name == "content")
                    {
                        content = await rd.ReadElementContentAsStringAsync();
                        break;
                    }

                    /* if (rd.NodeType == XmlNodeType.Element && rd.Name == "content")
                     {
                         Console.WriteLine(rd.ReadElementContentAsString());

                     }*/

                }
            }


            /*var chapter = await sqlSugarClient.Queryable<BookChapter>()
                .Where(t => t.Id == id)
                .FirstAsync();
                   return chapter;*/
            //Regex reg = new Regex("(&nbsp;.*?\r)");
            //content = Regex.Replace(content, "(&nbsp;.*?\r\n)", "<p>$1</p>");
            //content = Regex.Replace(content, "(&nbsp;.*?\n)", "<p>$1</p>");
            //  chapter.Content = chapter.Content;
            var contents = Regex.Replace(content, "<br>", "\n").Replace("&nbsp;", "").Split('\n')
              .Where(t => t != "");


            return contents;
        }


         public async Task<long> GetViews(long nid)
        {
            var bookEntension = await bookExtensionRepository.Find(nid);
            if (bookEntension == null)
            {
                bookEntension = new BookExtenstionEntity();
                bookEntension.Id = nid;
                bookEntension.Viewer++;
                bookEntension.UpdateTime = DateTime.Now;

                await bookExtensionRepository.Add(bookEntension);

            }

            return bookEntension.Viewer;
        }
        public async Task<long> AddViews(long nid)
        {
            var bookEntension = await bookExtensionRepository.Find(nid);
            if (bookEntension == null)
            {
                bookEntension = new BookExtenstionEntity();
                bookEntension.Id = nid;
                bookEntension.Viewer++;
                bookEntension.UpdateTime = DateTime.Now;

                await bookExtensionRepository.Add(bookEntension);

            }
            else
            {
                bookEntension.Viewer++;
                bookEntension.UpdateTime = DateTime.Now;

                await bookExtensionRepository.Update(bookEntension);
            }

            return bookEntension.Viewer;
        }
    }
}
